#include "../main.h"

#define BUFFSIZE_SIZE 64 * 1024

void read_router_cb(poll_event_t *poll_event, poll_event_element_t *node, struct epoll_event ev)
{
    char buf[BUFFSIZE_SIZE] = {0};
    int msglength = read(node->fd, buf, BUFFSIZE_SIZE);
    if (msglength > 0)
    {
        char bufcopy[msglength];
        memset(bufcopy, 0, msglength);
        memcpy(bufcopy, buf, msglength);
        append_router_data(ev.data.fd, bufcopy, msglength);
    }
}

void close_router_cb(poll_event_t *poll_event, poll_event_element_t *node, struct epoll_event ev)
{
    OUT_DEBUG(DEBUG, "in close_cb");
    poll_event_remove(poll_event, node->fd);
}

void accept_router_cb(poll_event_t *poll_event, poll_event_element_t *node, struct epoll_event ev)
{
    OUT_DEBUG(DEBUG, "in accept_router_cb");
    struct sockaddr_in clt_addr;
    socklen_t clt_len = sizeof(clt_addr);
    int listenfd = accept(node->fd, (struct sockaddr *)&clt_addr, &clt_len);
    fcntl(listenfd, F_SETFL, O_NONBLOCK);
    fprintf(stderr, "got the socket %d\n", listenfd);
    uint32_t flags = EPOLLIN | EPOLLRDHUP | EPOLLHUP;
    poll_event_element_t *p;
    poll_event_add(poll_event, listenfd, flags, &p);
    p->read_callback = read_router_cb;
    p->close_callback = close_router_cb;
}

int timeout_router_cb(poll_event_t *poll_event)
{
    if (!poll_event->data)
    {
        OUT_DEBUG(DEBUG, "init timeout counter");
        poll_event->data = calloc(1, sizeof(int));
    }
    else
    {
        int *value = (int *)poll_event->data;
        *value += 1;
    }
    return 0;
}
void *router_server()
{
    int port = 9001;
    struct sigaction sa;
    sa.sa_handler = SIG_IGN;
    sigaction(SIGPIPE, &sa, 0);

    int sock = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in svr_addr;
    memset(&svr_addr, 0, sizeof(svr_addr));
    svr_addr.sin_family = AF_INET;
    svr_addr.sin_addr.s_addr = htons(INADDR_ANY);
    svr_addr.sin_port = htons(port);
    set_reuseport(sock);
    int result = bind(sock, (struct sockaddr *)&svr_addr, sizeof(svr_addr));
    OUT_DEBUG(DEBUG, "bind port 9001 result:%d", result);

    listen(sock, 10);
    fcntl(sock, F_SETFL, O_NONBLOCK);

    poll_event_t *pe = poll_event_new(1000);
    pe->timeout_callback = timeout_router_cb;
    poll_event_element_t *p;
    poll_event_add(pe, sock, EPOLLIN, &p);
    p->accept_callback = accept_router_cb;
    p->close_callback = close_router_cb;
    p->cb_flags |= ACCEPT_CB;
    use_the_force(pe);

    return 0;
}

void set_reuseport(int sockfd)
{
    int opt = 1;
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (const void *)&opt, sizeof(opt));
}